/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ace.game.entity.player;

import ace.game.entity.body.BodyData;
import ace.game.Sprite;
import ace.game.entity.Entity;
import ace.game.entity.LivingEntity;
import ace.game.entity.weapon.Weapon;
import ace.game.entity.weapon.WeaponData;
import ace.geometry.Vertex2D;
import ace.system.StateManager;
import ace.system.Utilities;
import java.util.Vector;
import javax.microedition.lcdui.Graphics;

/**
 *
 * @author Hallucinogen
 */
public class Player extends LivingEntity  {
	protected Player() {
		//Initialize
		position	= new Vertex2D();
		mHealth		= 1;
		mAlive		= true;
        mScore      = 0;
        mLife       = 1;

        // circular weapon thingy
        mCircularWeaponCount            = 0;
        mCircularWeaponInitialDegree    = 0;
        mCircularWeaponRadius           = 30;
	}

	public Player(BodyData body) {
		//Initialize
		this();

		//Initialize data
		mBody	= body;
        mHealth	= mBody.getHealthMax();
	}

    public void respawn() {
        if (mLife > 0) {
            --mLife;
            mHealth = mBody.getHealthMax();
            mAlive  = true;
            setImmortal(true);
        } else {
            mAlive = false;
        }
    }

	public BodyData getData()   {	return mBody;		}
    public Vector getWeapons()  {   return mWeapons;    }
    public int getScore()       {   return mScore;      }
    public int getLife()        {   return mLife;       }

    public void setData(BodyData data)   {
        mBody = data;
    }

    public void setImmortal(boolean immortal) {
        mImmortal       = immortal;
        mImmortalTime   = 0;
    }

    public void damage(int damage) {
        if (!mImmortal) {
            super.damage(damage);
        }
    }

	public void update(long time) {
		mBody.getSprites().update(time);
        mImmortalTime += time;
        if (mImmortalTime > 3000) {
            setImmortal(false);
        }
		updateWeapons(time);
    }

	private void updateWeapons(long time) {
		if (mWeapons == null) return;

        int circularWeapon = 0;
		for (int i = 0, n = mWeapons.size(); i < n; ++i) {
			final Weapon weapon = (Weapon)mWeapons.elementAt(i);
			weapon.update(time);

            // restrict weapon position based on weapon type
            final int weaponType = weapon.getData().getWeaponType();
			switch (weaponType) {
				case WeaponData.WEAPON_TYPE_MAIN:
					weapon.position.x = position.x;
					weapon.position.y = position.y - 15;
				break;
				case WeaponData.WEAPON_TYPE_LEFT:
					weapon.position.x = position.x - 12;
					weapon.position.y = position.y + 8;
				break;
				case WeaponData.WEAPON_TYPE_RIGHT:
					weapon.position.x = position.x + 12;
					weapon.position.y = position.y + 8;
				break;
                case WeaponData.WEAPON_TYPE_CIRCULAR:
                    final float degree = mCircularWeaponInitialDegree + circularWeapon * 360 / mCircularWeaponCount;
                    final float x = mCircularWeaponRadius * (float)Math.sin(Math.toRadians(degree));
                    final float y = mCircularWeaponRadius * (float)Math.cos(Math.toRadians(degree));

                    weapon.position.x = position.x + x;
                    weapon.position.y = position.y + y;
                    ++circularWeapon;
                break;
			}
		}

        // update circular weapon position
        mCircularWeaponInitialDegree    = (mCircularWeaponInitialDegree + 0.25f * time) % 360;
	}

	public void draw(Graphics g, int startX, int startY, int endX, int endY) {
		//Get current sprite
		Sprite Current = mBody.getSprites();
		if (Current == null) return;

        if (mImmortal) {
            if (Math.sin(Math.toRadians(mImmortalTime * mImmortalTime / 1000)) < 0) return;
        }

		//Get rect
		int Left	= (int)(position.x - startX);
		int Top		= (int)(position.y - startY);

		//Ensure in drawing area
		if (Left + Current.getWidth() < 0)					return;
		else if(Left > StateManager.instance().getWidth())	return;
		else if (Top + Current.getHeight() < 0)				return;
		else if (Top > StateManager.instance().getHeight())	return;

		//Draw sprite
		Current.setPosition(Left, Top);
		Current.draw(g, Graphics.VCENTER | Graphics.HCENTER);

		// draw weapons
		drawWeapons(g, startX, startY, endX, endY);
	}

	private void drawWeapons(Graphics g, int startX, int startY, int endX, int endY) {
		if (mWeapons == null) return;
		for (int i = 0, n = mWeapons.size(); i < n; ++i) {
			final Weapon weapon = (Weapon)mWeapons.elementAt(i);
			weapon.draw(g, startX, startY, endX, endY);
		}
	}

    public void addScore(int score) {
        mScore += score;
    }

    public void addHealth(int health) {
        mHealth += health;
        if (mHealth > mBody.getHealthMax()) {
            mHealth = mBody.getHealthMax();
        }
    }

    public void addLife(int life) {
        mLife += life;
        if (mLife > 7) {
            mLife = 7;
            addScore(1000);
        }
    }

	public void addWeapon(Weapon weapon) {
		if (mWeapons == null) {
			mWeapons = new Vector();
		}

		mWeapons.addElement(weapon);

        // if circular, give degree
        if (weapon.getData().getWeaponType() == WeaponData.WEAPON_TYPE_CIRCULAR) {
            mCircularWeaponCount = 0;
            for (int i = 0; i < mWeapons.size(); ++i) {
                final Weapon tWeapon = (Weapon)mWeapons.elementAt(i);
                if (tWeapon.getData().getWeaponType() == WeaponData.WEAPON_TYPE_CIRCULAR) {
                    ++mCircularWeaponCount;
                }
            }
        }
	}

	public void removeWeapon(Weapon weapon) {
		if (mWeapons == null) return;

		mWeapons.removeElement(weapon);

        // if circular, give degree
        if (weapon.getData().getWeaponType() == WeaponData.WEAPON_TYPE_CIRCULAR) {
            mCircularWeaponCount = 0;
            for (int i = 0; i < mWeapons.size(); ++i) {
                final Weapon tWeapon = (Weapon)mWeapons.elementAt(i);
                if (tWeapon.getData().getWeaponType() == WeaponData.WEAPON_TYPE_CIRCULAR) {
                    ++mCircularWeaponCount;
                }
            }
        }
	}

    public void removeWeaponWithData(WeaponData data) {
		if (mWeapons == null) return;

		for (int i = 0, n = mWeapons.size(); i < n; ++i) {
            final Weapon weapon = (Weapon)mWeapons.elementAt(i);
            if (weapon.getData() == data) {
                removeWeapon(weapon);
                // assume there's only one weapon of such
                break;
            }
        }
	}

	// parts
	protected BodyData mBody;
	protected Vector mWeapons;
    protected int mCircularWeaponCount;
    protected float mCircularWeaponInitialDegree;
    protected float mCircularWeaponRadius;

	// player specific
    protected int mLife;
    protected boolean mImmortal;
    protected int mImmortalTime;

    // gameplay specific
    protected int mScore;
}
